package mage.factory.handler;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import mage.factory.rules.RuleParser;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

public class CardCreatorHandler extends CardHandler {
	private static Logger log = LogManager.getLogger(CardCreatorHandler.class);
	
	public boolean process(CardElement cd,String set){
		return (
				(cd.getLoyalty().equals("")) &&
				(cd.getLife().equals("")) &&
				(cd.getHand().equals("")) &&
				(!cd.getTypeList().contains("Plane")) &&
				(!cd.getTypeList().contains("Scheme")) &&
				(!cd.getTypeList().contains("Ongoing")) &&
				(!cd.getTypeList().contains("Vanguard")) &&
				(!cd.getTypeList().contains("Shrine")) &&
				(!cd.getTypeList().contains("World")) &&
				(!cd.getTypeList().contains("Arcane")) &&
				(!cd.getTypeList().contains("Trap"))  &&
				(!cd.isMulti()) && 
				(set.equalsIgnoreCase("2ED")) 
				//("Abbey Gargoyles")) //FIXME: remove this...
				//(!cd.getTypeList().contains("Lair")) 
				//(!cd.getTypeList().contains("Urza's"))
			);
	}
	public void toRule(String filename){
		try {	
			BufferedWriter out = new BufferedWriter(new FileWriter(
					new File(filename)
				));
			for (DefaultHandlerElement se : super.elements) {
				CardElement ce = (CardElement) se;
				String[] rules = ce.getRule().split("\\|");
				for (int i=0; i < rules.length; i++){
					out.write(ce.getName()+";"+ce.getSets()[0]+";"+rules[i]+"\n");
				}
			}
			out.close();
		} catch (IOException e) {
		}
		
	}
	public void toClass(List<DefaultHandlerElement> elements,String basename){
		for (DefaultHandlerElement se : super.elements) {
			CardElement ce = (CardElement) se;
			String[] sets = ce.getSets();
			for (int i=0;i<sets.length;i++){
				if(this.process(ce,sets[i])){
					ce.setPackageName(this.codeToName(sets[i], elements));
					System.out.println(ce.getClassName()+"\t->\t"+sets[i] + "\t->\t" + ce.getPackageName());
					String filename = basename + 
										"\\" + 
										ce.getPackageName() +
										"\\" + 
										ce.getClassName() +
										".java";
					
					try {	
						BufferedWriter out = new BufferedWriter(new FileWriter(
								new File(filename)
							));
						out.write(CardCreatorHandler.createCard(ce).toClass());
						out.close();
					} catch (IOException e) {
					}
					
				}
			}
		}
		
	}
	
	public static DefaultHandlerElement createCard(CardElement ce){
		CardCreatorBase dhe = null;
		
		List<String> types = ce.getTypeList();
		if(types.contains("Land") && types.contains("Basic")){
			//FIXME: add terre doppie
			dhe = new BasicLandBase();
		}else{
			dhe =  new CardBase();
		}
		dhe.setCardElement(ce);
		return dhe;
	}
}

abstract class CardCreatorBase implements DefaultHandlerElement{
	protected CardElement ce = null;
	public void setCardElement(CardElement ce){
		this.ce=ce;
	}
	
	protected String getJavaPackage(){
		return "package mage.sets."+this.getPackageName()+";\n";
	}
	protected String getJavaImport(){
		return "import java.util.UUID;\n"+
				"import mage.Constants.CardType;\n"+
				"import mage.Constants.Duration;\n"+
				"import mage.Constants.Rarity;\n"+
				"import mage.Constants.Zone;\n"+
				"import mage.MageInt;\n"+
				"import mage.abilities.keyword.CascadeAbility;\n"+
				"import mage.abilities.keyword.ExaltedAbility;\n"+
				"import mage.cards.CardImpl;\n";
	}
	protected String getJavaClassStart(){
		return "\tpublic class "+this.getClassName()+" extends CardImpl<"+this.getClassName()+"> {\n\tprivate static final long serialVersionUID = 1L;\n\tpublic "+this.getClassName()+" (UUID ownerId) {\n";
	}
	protected String getJavaClassSuper(){
		StringBuffer sb = new StringBuffer();
		sb.append("\t\tsuper(ownerId,");
		sb.append(this.ce.getNumbers()[0]);
		sb.append(",\"");
		sb.append(this.ce.getName());
		sb.append("\",");
		sb.append(this.getJavaRarity(this.ce.getRaritys()[0],this.ce.getMainType()));
		sb.append(",new CardType[]{");
		sb.append(this.getJavaTypes(this.ce.getMainType()));
		sb.append("}, \"");
		sb.append(this.getJavaCost(this.ce.getCost()));			//FIXME: add ManacostVariableValue
		sb.append("\");\n");
		sb.append("\t\tthis.expansionSetCode = \"");
		sb.append(this.ce.getSets()[0]);
		sb.append("\";\n");
		sb.append(this.getJavaColors(this.ce.getCost()));
		if(!"".equalsIgnoreCase(this.ce.getLegendary())){
			sb.append("\t\tthis.supertype.add(\"Legendary\");\n");
		}
		sb.append(this.getJavaOtherTypes(this.ce.getOtherType()));
		sb.append(this.getJavaPowTgh(this.ce.getPow(),this.ce.getTgh()));

		//this.subtype.add()
		//FIXME:
		/*
		Legendary
		Aura
		Equipment
		Fortification
		Snow
		Shrine
		World
		Arcane
		Trap
		Basic
		Lair
		Locus
		Urza's
		Ongoing

		*/
		
		
		
		//SORCERY: this.getSpellAbility().addEffect(new DamageAllEffect(2, FilterCreaturePermanent.getDefault()));
		//ISTANT: this.getSpellAbility().addTarget(new TargetCreaturePermanent());
		//ISTANT: this.getSpellAbility().addEffect(new BoostTargetEffect(4, 2, Duration.EndOfTurn));
		//ISTANT: this.getSpellAbility().addEffect(new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn));
		//CREATURE: this.addAbility(HasteAbility.getInstance());
		//CREATURE: this.addAbility(new CascadeAbility());
		//ENCHANTMENT: this.addAbility(new ExaltedAbility());
	    //ENCHANTMENT: this.addAbility(new CascadeAbility());

		
		//Alternative cost
		//Cost cost = new CompositeCost(new GenericManaCost(1), new ReturnToHandTargetCost(new TargetControlledPermanent(filter)), COST_DESCRIPTION);
        //this.getSpellAbility().addAlternativeCost(new AlternativeCostImpl(ALTERNATIVE_COST_DESCRIPTION, cost));
        //this.addAbility(new EntersBattlefieldTappedAbility());
        //this.addAbility(new WhiteManaAbility());
        //this.addAbility(new BlueManaAbility());


		
		
		return sb.toString();
	}
	protected String getJavaTypes(String types){
		StringBuffer sb = new StringBuffer();
		if(types.contains("Artifact")){sb.append("CardType.ARTIFACT,");}
		if(types.contains("Creature")){sb.append("CardType.CREATURE,");}
		if(types.contains("Enchantment")){sb.append("CardType.ENCHANTMENT,");}
		if(types.contains("Instant")){sb.append("CardType.INSTANT,");}
		if(types.contains("Land")){sb.append("CardType.LAND,");}
		if(types.contains("Planeswalker")){sb.append("CardType.PLANESWALKER,");}
		if(types.contains("Sorcery")){sb.append("CardType.SORCERY,");}
		if(types.contains("Tribal")){sb.append("CardType.TRIBAL,");}
		if(sb.length()>1){
			sb.deleteCharAt(sb.length()-1);
		}
		return sb.toString();
	}
	protected String getJavaCost(String cost){
		StringBuffer sb = new StringBuffer();
		for(int i=0; i < cost.length(); i++){
			sb.append("{"+cost.charAt(i)+"}");
		}
		return sb.toString();
	}
	protected String getJavaColors(String cost){
		StringBuffer sb = new StringBuffer();
		String head = "\t\tthis.color.set";
		String tail = "(true);\n";
		ArrayList<String> colors = new ArrayList<String>();
		for(int i=0; i < cost.length(); i++){
			if ("R".equalsIgnoreCase("Red"+cost.charAt(i))){}
			if ("W".equalsIgnoreCase("White"+cost.charAt(i))){}
			if ("G".equalsIgnoreCase("Green"+cost.charAt(i))){}
			if ("B".equalsIgnoreCase("Black"+cost.charAt(i))){}
			if ("U".equalsIgnoreCase("Blue"+cost.charAt(i))){}
		}
		for (int i=0; i<  colors.size(); i++){
			sb.append(head+colors.get(i)+tail);
		}
		return sb.toString(); 
	}
	protected String getJavaOtherTypes(String others){
		String[] temp = others.split(";");
		StringBuffer sb = new StringBuffer();
		if (temp.length>0){
			for (int i=0; i < temp.length; i++){
				sb.append("\t\tthis.subtype.add(\"" + temp[i] + "\");\n");
			}
		}
		return sb.toString();
	}
	protected String getJavaPowTgh(String pow, String tgh){
		if(!"".equalsIgnoreCase(pow)){
			return "\t\tthis.power=new MageInt("+pow+");\n\t\tthis.toughness=new MageInt("+tgh+");\n";
		}else{
			return "";
		}
	}
	protected String getJavaRarity(String rarity,String type){
		if("M".equalsIgnoreCase(rarity)){return "Rarity.MYTHIC";}
		if("R".equalsIgnoreCase(rarity)){return "Rarity.RARE";}
		if("U".equalsIgnoreCase(rarity)){return "Rarity.UNCOMMON";}
		if("C".equalsIgnoreCase(rarity)){
			if("Land".equalsIgnoreCase(type)){
				return "Rarity.LAND";
			}else{
				return "Rarity.COMMON";
			}
		}
		return "Rarity.NA";
	}
	protected String getJavaClassEnd(){
		return "}\n\tpublic "+this.getClassName()+" (final "+this.getClassName()+" card) {super(card);}\n" +
	    		"\t@Override\n"+
	    		"\tpublic "+this.getClassName()+" copy() {return new "+this.getClassName()+"(this);}\n";
	}
	@Override
	public String getPackageName() {
		return this.ce.getPackageName();
	}
	@Override
	public String getClassName() {
		return this.ce.getClassName();
	}
	@Override
	public String toClass() {
		StringBuffer sb = new StringBuffer();
		sb.append(this.getJavaPackage());
		sb.append(this.getJavaImport());
		sb.append(this.getJavaClassStart());
		sb.append(this.getJavaClassSuper());
		sb.append(this.getConstructureDetails());
		sb.append(this.getJavaClassEnd());
		sb.append(this.getAdditionalMethods());
		sb.append("}\n");
		return sb.toString();
	}
	/**
	 * This is to add other things... i.e. Equipment ability etc...
	 * @return
	 */
	public abstract String getConstructureDetails();
	/**
	 * This is to add other things after constructor
	 * @return
	 */
	public abstract String getAdditionalMethods();
}

class CardBase extends  CardCreatorBase implements DefaultHandlerElement{
	protected static final RuleParser parser = new RuleParser();
	
	@Override
	public String getConstructureDetails() {
		return "";
	}
	@Override
	public String getAdditionalMethods() {
		return "";
	}
}

class BasicLandBase extends  CardCreatorBase implements DefaultHandlerElement{
	/*
	May be ARtifact or BAsic Land
	*/
	@Override
	public String getConstructureDetails() {
		return "";
	}
	@Override
	public String getAdditionalMethods() {
		return "";
	}
	@Override
	public String toClass() {
		StringBuffer sb = new StringBuffer();
		sb.append(super.getJavaPackage());
		sb.append("import java.util.UUID;\n");
		sb.append("public class "+this.ce.getName()+" extends mage.cards.basiclands."+this.ce.getName()+" {\n\tprivate static final long serialVersionUID = 1L;\n");
		sb.append("\tpublic "+this.ce.getName()+"(UUID ownerId) {\n\t\tsuper(ownerId,"+this.ce.getNumbers()[0]+");\n\t\tthis.expansionSetCode = \""+this.ce.getSets()[0]+"\";\n\t}\n");
		sb.append("\tpublic "+this.ce.getName()+"(final "+this.ce.getName()+" card) {\n\t\tsuper(card);\n\t}\n");
		sb.append("\t@Override\n\tpublic "+this.ce.getName()+" copy() {\n\t\treturn new "+this.ce.getName()+"(this);\n\t}\n}\n");
		return sb.toString();
	}
}